package com.blm.service.impl;

import com.blm.common.constants.CacheConstant;
import com.blm.common.constants.ExceptionConstant;
import com.blm.dto.FoodCreateDTO;
import com.blm.entity.Food;
import com.blm.exception.CommonException;
import com.blm.repository.FoodRepository;
import com.blm.service.MerchantFoodService;
import com.blm.service.StoreService;
import com.blm.util.RedisUtil;
import com.blm.vo.FoodVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class MerchantFoodServiceImpl implements MerchantFoodService {

    @Autowired
    private FoodRepository foodRepository;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private StoreService storeService;

    
    @Override
    @Cacheable(value = CacheConstant.FOOD_MERCHANT, key = "#storeId + '_' + #categoryId + '_' + #status")
    public List<FoodVO> listFoods(Long merchantId, Long storeId, Long categoryId, Food.FoodStatus status) {
        storeService.verifyStoreOwner(storeId, merchantId);
        // 根据参数过滤商品
        List<Food> foods;
        if (categoryId != null && status != null) {
            foods = foodRepository.findByStoreIdAndCategoryIdAndStatus(storeId, categoryId, status);
        } else if (categoryId != null) {
            foods = foodRepository.findByStoreIdAndCategoryId(storeId, categoryId);
        } else if (status != null) {
            foods = foodRepository.findByStoreIdAndStatus(storeId,status);
        } else {
            foods = foodRepository.findONByStoreId(storeId);
        }
        
        return foods.stream().map(f -> {
            FoodVO vo = new FoodVO();
            BeanUtils.copyProperties(f, vo);
            return vo;
        }).collect(Collectors.toList());
    }

    @Override
    @Transactional
    @CacheEvict(value = CacheConstant.STORE_DETAIL, key = "#storeId")
    public FoodVO createFood(Long merchantId, Long storeId, FoodCreateDTO dto) {
        storeService.verifyStoreOwner(storeId, merchantId);
        Food food = new Food();
        BeanUtils.copyProperties(dto, food);
        food.setStoreId(storeId);
        food.setSales(0);
        food.setStatus(Food.FoodStatus.OFF_SHELF);
        food.setCreatedAt(LocalDateTime.now());
        food.setUpdatedAt(LocalDateTime.now());
        foodRepository.insert(food);
        redisUtil.clearCache(CacheConstant.FOOD_MERCHANT, storeId);
        redisUtil.clearCache(CacheConstant.FOOD_USER, storeId);
        Food saved = foodRepository.findById(food.getId())
            .orElseThrow(() -> new CommonException(ExceptionConstant.FOOD_NOT_FOUND));
        FoodVO vo = new FoodVO();
        BeanUtils.copyProperties(saved, vo);
        return vo;
    }

    @Override
    @Transactional
    @Caching(evict = {
            @CacheEvict(value = CacheConstant.STORE_DETAIL, key = "#storeId"),
            @CacheEvict(value = CacheConstant.FOOD_DETAIL, key = "#foodId")
    })
    public FoodVO updateFood(Long merchantId, Long storeId, Long foodId, FoodCreateDTO dto) {
        storeService.verifyStoreOwner(storeId, merchantId);
        Food food = foodRepository.findById(foodId)
            .orElseThrow(() -> new CommonException(ExceptionConstant.FOOD_NOT_FOUND));
        if (!food.getStoreId().equals(storeId)) {
            throw new CommonException(ExceptionConstant.STORE_UNAUTHORIZED);
        }
        BeanUtils.copyProperties(dto, food);
        food.setUpdatedAt(LocalDateTime.now());

        if(dto.getStatus() == 0){
            food.setStatus(Food.FoodStatus.OFF_SHELF);
        }else{
            food.setStatus(Food.FoodStatus.ON_SHELF);
        }

        if(food.getStatus() == Food.FoodStatus.SUSPENDED) {
            food.setStatus(Food.FoodStatus.PENDING);
        }
        foodRepository.update(food);
        redisUtil.clearCache(CacheConstant.FOOD_MERCHANT, storeId);
        redisUtil.clearCache(CacheConstant.FOOD_USER, storeId);
        Food updated = foodRepository.findById(foodId)
            .orElseThrow(() -> new CommonException(ExceptionConstant.FOOD_NOT_FOUND));
        FoodVO vo = new FoodVO();
        BeanUtils.copyProperties(updated, vo);
        return vo;
    }

    @Override
    @Transactional
    @Caching(evict = {
            @CacheEvict(value = CacheConstant.STORE_DETAIL, key = "#storeId"),
            @CacheEvict(value = CacheConstant.FOOD_DETAIL, key = "#foodId")
    })
    public void deleteFood(Long merchantId, Long storeId, Long foodId) {
        storeService.verifyStoreOwner(storeId, merchantId);
        Food food = foodRepository.findById(foodId)
                .orElseThrow(() -> new CommonException(ExceptionConstant.FOOD_NOT_FOUND));
        if (!food.getStoreId().equals(storeId)) {
            throw new CommonException(ExceptionConstant.FOOD_UNAUTHORIZED);
        }
        foodRepository.deleteByIdAndStoreId(foodId, storeId);
        redisUtil.clearCache(CacheConstant.FOOD_MERCHANT, storeId);
        redisUtil.clearCache(CacheConstant.FOOD_USER, storeId);
    }

    @Override
    @Transactional
    @Caching(evict = {
            @CacheEvict(value = CacheConstant.STORE_DETAIL, key = "#storeId"),
            @CacheEvict(value = CacheConstant.FOOD_DETAIL, key = "#foodId")
    })
    public void updateStatus(Long merchantId, Long storeId, Long foodId, Food.FoodStatus status) {
        storeService.verifyStoreOwner(storeId, merchantId);
        Food food = foodRepository.findById(foodId)
                .orElseThrow(() -> new CommonException(ExceptionConstant.FOOD_NOT_FOUND));
        if (!food.getStoreId().equals(storeId)) {
            throw new CommonException(ExceptionConstant.FOOD_UNAUTHORIZED);
        }
        foodRepository.updateStatus(foodId, storeId, status, LocalDateTime.now());
        redisUtil.clearCache(CacheConstant.FOOD_MERCHANT, storeId);
        redisUtil.clearCache(CacheConstant.FOOD_USER, storeId);
    }

    @Override
    public FoodVO getFoodByStoreIdAndFoodId(Long merchantId, Long storeId, Long foodId) {
        storeService.verifyStoreOwner(storeId, merchantId);
        Food food = foodRepository.findById(foodId)
                .orElseThrow(() -> new CommonException(ExceptionConstant.FOOD_NOT_FOUND));
        if (!food.getStoreId().equals(storeId)) {
            throw new CommonException(ExceptionConstant.FOOD_UNAUTHORIZED);
        }
        FoodVO vo = new FoodVO();
        BeanUtils.copyProperties(food, vo);
        return vo;
    }
}